package com.sengled.cloud.biz.union.mgt.common.util;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class RedisUtil {

	public static StringRedisTemplate redisTemplate;

	public static void setRedisTemplate(StringRedisTemplate redisTemplate) {
		RedisUtil.redisTemplate = redisTemplate;
	}

	private static StringRedisSerializer getSerializer() {
		StringRedisTemplate redisTemplate = getRedisTemplate();
		return (StringRedisSerializer) redisTemplate.getStringSerializer();
	}

	private static StringRedisTemplate getRedisTemplate() {
		return redisTemplate;
	}


	/**
	 * 根据key获取String类型的value
	 * 
	 * @param key
	 * @return
	 */
	public static String getStrValueByKey(final String key) {
		final StringRedisSerializer serializer = getSerializer();
		StringRedisTemplate redisTemplate = getRedisTemplate();
		return redisTemplate.execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection conn) throws DataAccessException {
				return serializer.deserialize(conn.get(serializer.serialize(key)));
			}
		});
	}

	/**
	 * 添加String类型数据
	 * 
	 * @param key
	 * @param value
	 * @autor:dongyunqi
	 * @createDate:2015-1-29上午10:34:10
	 */
	public static void setStrValueByKey(final String key, final String value) {
		final StringRedisSerializer serializer = getSerializer();
		getRedisTemplate().execute(new RedisCallback<Boolean>() {
			@Override
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				connection.set(serializer.serialize(key), serializer.serialize(value));
				return true;
			}
		});
	}
	/**
	 * 添加String类型数据
	 *
	 * @param key
	 * @param value
	 * @param expirationTime  seconds
	 * @autor:dongyunqi
	 * @createDate:2015-1-29上午10:34:10
	 */
	public static void setStrValueByKey(final String key, final String value, final long expirationTime) {
		final StringRedisSerializer serializer = getSerializer();
		getRedisTemplate().execute(new RedisCallback<Boolean>() {
			@Override
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {

				connection.set(serializer.serialize(key), serializer.serialize(value));
				connection.expire(serializer.serialize(key), expirationTime);
				return true;
			}
		});
	}

	/**
	 * 根据key删除value
	 * 
	 * @param key
	 */
	public static void removeValueByKey(String key) {
		getRedisTemplate().delete(key);
	}

	/**
	 * 获取所有心跳超时的token的集合
	 * 
	 * @return
	 * @autor:dongyunqi
	 * @createDate:2015-6-13上午10:21:56
	 */
	public static List<String> getHeartBeatTimeoutDev() {
		final StringRedisSerializer serializer = getSerializer();
		StringRedisTemplate redisTemplate = getRedisTemplate();
		final long THIRTY_MINUTES = 30 * 60 * 1000;
		final long ONE_MINUTES = 60 * 1000;
		/*
		 * 获取所有保存的所有设备心跳的key的集合
		 */
		final List<String> heartBeatTokens = new ArrayList<String>();
		heartBeatTokens.addAll(redisTemplate.keys("*_appheartbeat"));
		/*
		 * 轮寻设备心跳的key的集合，找出心跳超时的设备信息
		 */
		List<String> timeoutTokens = new ArrayList<String>();
		if (heartBeatTokens != null && heartBeatTokens.size() > 0) {
			timeoutTokens = redisTemplate.execute(new RedisCallback<List<String>>() {
				public List<String> doInRedis(RedisConnection conn) throws DataAccessException {
					List<String> resutl = new ArrayList<String>();
					for (String key : heartBeatTokens) {
						List<byte[]> values = conn.hMGet(serializer.serialize(key), serializer.serialize("newestTime"), serializer.serialize("initTime"), serializer.serialize("token"));
						long newestTime = Long.valueOf(new String(values.get(0)));
						long initTime = Long.valueOf(new String(values.get(1)));
						String token = new String(values.get(2));
						long currentTimeMillis = System.currentTimeMillis();
						/*
						 * 判断是否最开始看直播的时间是否超过了30分钟，并且最近一次心跳时间大于一分钟，如果是则为超时
						 */
						if ((currentTimeMillis - initTime) > THIRTY_MINUTES && (currentTimeMillis - newestTime) > ONE_MINUTES) {
							resutl.add(token);
						}
					}
					return resutl;
				}
			});
		}
		return timeoutTokens;
	}

	/**
	 * 更新直播心跳时间
	 * 
	 * @param token
	 * @autor:dongyunqi
	 * @createDate:2015-6-13上午11:08:41
	 */
	public static void updateHeartBeatTime(final String token) {
		StringRedisTemplate redisTemplate = getRedisTemplate();
		final StringRedisSerializer serializer = getSerializer();
		redisTemplate.execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection conn) throws DataAccessException {
				conn.hSet(serializer.serialize(token + "_appheartbeat"), serializer.serialize("newestTime"), serializer.serialize(System.currentTimeMillis() + ""));
				return null;
			}
		});
	}

	public static void delByKey(final String key) {
		System.out.println("************delKey [ " + key + " ]***************");
		getRedisTemplate().execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection conn) throws DataAccessException {
				conn.del(getSerializer().serialize(key));
				return null;
			}
		});
	}

	public static boolean isKeyExist(final String key) {
		return getRedisTemplate().execute(new RedisCallback<Boolean>() {
			@Override
			public Boolean doInRedis(RedisConnection conn) throws DataAccessException {
				return conn.exists(getSerializer().serialize(key));
			}
		});
	}
	
	public static boolean setIfAbsent(String key, String value) {
		return redisTemplate.opsForValue().setIfAbsent(key, value);
	}

	public static String getAndSet(String key, String value){
    	return redisTemplate.opsForValue().getAndSet(key, value);
    }

    public static boolean putIfAbsent(String key, String index, String value){
    	return getRedisTemplate().opsForHash().putIfAbsent(key, index, value);
	};

	public static<HK, HV> Map<HK, HV> pull(String key){
		return getRedisTemplate().<HK, HV>opsForHash().entries(key);
	}
}
